﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace EasyComm
{
    public class ServiceProxy<TContract> : ClientBase<TContract>, IDisposable
        where TContract : class
    {
        public delegate void ServiceProxyDelegate<T>(TContract proxy);

        public ServiceProxy()
            : base(typeof(TContract).ToString())
        {
        }

        public ServiceProxy(string endpointConfigurationName)
            : base(endpointConfigurationName)
        {
        }

        public ServiceProxy(Binding binding, EndpointAddress address)
            : base(binding, address)
        {
        }

        protected override TContract CreateChannel()
        {
            return base.CreateChannel();
        }

        public TContract Proxy { get { return this.Channel; } }

        public static void Call(ServiceProxyDelegate<TContract> proxyDelegate)
        {
            Call(proxyDelegate, typeof(TContract).ToString());
        }

        public static void Call(ServiceProxyDelegate<TContract> proxyDelegate, string endpointConfigurationName)
        {
            ChannelFactory<TContract> channel = new ChannelFactory<TContract>(endpointConfigurationName);
            try
            {
                proxyDelegate(channel.CreateChannel());
            }
            finally
            {
                if (channel.State == CommunicationState.Faulted)
                {
                    channel.Abort();
                }
                else
                {
                    try
                    {
                        channel.Close();
                    }
                    catch
                    {
                        channel.Abort();
                    }
                }
            }
        }

        public void Dispose()
        {
            if (this.State == CommunicationState.Faulted)
            {
                base.Abort();
            }
            else
            {
                try
                {
                    base.Close();
                }
                catch
                {
                    base.Abort();
                }
            }
        }
    }
}
